<!--
  超级表格组件使用方式
  1. 表格数据结构：
  const tableHeader = ref(["项目title", "结果title", "程度title"]);
  const tableData1 = ref([
    ['面色1', '面白2', '轻微'],
    ['眼周1', '无黑眼圈2', '--'],
    ['脸颊1', ['无斑2', '无痘2'], ['-', '-']],
    ['眉间1', '无痘', '轻微'],
    ['额头1', ['无皱纹', '无痘'], ['-', '-']],
    ['额头1', ['无皱纹', '无痘'], ['-', '-']],
  ]);
  2. 表格组件使用方式：
  <SuperTable
    :header-data="tableHeader"
    :table-data="tableData1"
    :splitNum="2"
  />
  <SuperTable
    header-position="left"
    :header-data="tableHeader"
    :table-data="tableData1"
  />
  3. 插槽使用方式：
  <SuperTable
    :header-data="tableHeader"
    :table-data="tableData1"
    :splitNum="2"
  >
    <template #header="{ header, headerIndex }">
      <div class="custom-header">
        <span>{{ header }} {{ headerIndex }}</span>
      </div>
    </template>
  </SuperTable>

-->
<template>
  <div
    v-if="tableDataResult.length"
    class="super-table-wrapper"
    :class="tableContainerClass"
  >
    <!-- 表头在顶部时，显示表头，如果在左侧，直接是body数据 -->
    <div
      v-if="isHeaderTop"
      class="t-header"
      :style="{ gridTemplateColumns: getGridTemplateColumns() }"
    >
      <div
        v-for="(item, index) in tableHeaders"
        :key="index"
        class="t-th"
        :class="{ 'gap-cell': isGapCell(item) }"
      >
        <!-- 表头插槽 -->
        <slot
          name="header"
          :header="item"
          :headerIndex="index"
          v-if="!isGapCell(item)"
        >
          {{ item }}
        </slot>
      </div>
    </div>

    <!-- 表格主体 -->
    <div class="t-body">
      <div
        v-for="(row, rowIndex) in tableDataResult"
        :key="rowIndex"
        :style="{ gridTemplateColumns: getGridTemplateColumns() }"
        class="t-row"
      >
        <template v-for="(cell, cellIndex) in row" :key="cellIndex">
          <!-- 非数组单元格 -->
          <div
            v-if="!isArray(cell)"
            class="t-td"
            :class="{ 'gap-cell': isGapCell(cell) }"
          >
            <!-- 单元格插槽 -->
            <slot
              v-if="!isGapCell(cell)"
              name="cell"
              :cell="cell"
              :row="row"
              :rowIndex="rowIndex"
              :cellIndex="cellIndex"
            >
              {{ cell }}
            </slot>
          </div>

          <!-- 数组单元格（嵌套） -->
          <div v-else class="t-td" :class="{ 'gap-cell': isGapCell(cell) }">
            <div
              v-for="(nestedCell, nestedIndex) in cell"
              :key="nestedIndex"
              class="t-td"
              :class="{ 'gap-cell': isGapCell(nestedCell) }"
            >
              <!-- 嵌套单元格插槽 -->
              <slot
                v-if="!isGapCell(nestedCell)"
                name="nested-cell"
                :cell="nestedCell"
                :parentCell="cell"
                :row="row"
                :rowIndex="rowIndex"
                :cellIndex="cellIndex"
                :nestedIndex="nestedIndex"
                >
                {{ nestedCell }}
              </slot>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, ref } from "vue";

const props = defineProps({
  // 表头数据
  headerData: { type: Array, default: ["项目", "结果", "程度"] },
  // 表格数据
  tableData: { type: Array, default: [] },
  // 表头在顶部时，分割列数，默认1，表头在左侧不支持分割，无意义
  splitNum: { type: Number, default: 1 },
  // 表头位置 top | left
  headerPosition: { type: String, default: "top" },
  // 表头在左侧的时候表头的宽度
  headerLeftWidth: { type: String, default: "80px" },
  // 表头在顶部且分割列数大于1的时候，分割列的宽度
  splitColumnWidth: { type: String, default: "20px" },
  // 是否带斑纹
  striped: { type: Boolean, default: true },
  // 是否反转斑马纹
  stripeReverse: { type: Boolean, default: false },
  // 空数据提示文本
  emptyText: { type: String, default: "暂无数据" },
});

/** 表头是否是在顶部 */
const isHeaderTop = computed(() => {
  return props.headerPosition === "top" ? true : false;
});

/** 计算斑马纹类名 */
const stripeClass = computed(() => {
  if (!props.striped) return ''
  return props.stripeReverse ? 'stripe-reverse' : 'stripe-normal'
})

/** 表格容器类 */
const tableContainerClass = computed(() => [
  isHeaderTop.value ? 'table-header-top' : 'table-header-left',
  stripeClass.value
]);

/** 判断是否是分割单元格 */
const isGapCell = (cell) => cell === true;

/** 判断是否是数组 */
const isArray = (data) => {
  return Array.isArray(data);
};

/** 获取列模板 */
const getGridTemplateColumns = () => {
  if (!isHeaderTop.value) {
    return (
      `${props.headerLeftWidth} ` + `1fr `.repeat(props.tableData.length).trim()
    );
  }

  // 创建列模板数组
  const columns = [];
  for (let i = 0; i < props.splitNum; i++) {
    // 添加数据列（等宽）
    if (i > 0) {
      columns.push(props.splitColumnWidth); // gap-cell 固定宽度
    }
    // 添加数据列（等宽）
    for (let j = 0; j < props.headerData.length; j++) {
      columns.push("1fr");
    }
  }
  return columns.join(" ");
};

/** 表头在顶部时，分割后的表头 */
const tableHeaders = computed(() => {
  return Array.from({ length: props.splitNum }, (_, i) =>
    i ? [true, ...props.headerData] : props.headerData
  ).flat();
});

/** 表头在顶部时，分割数据 */
const headerTopTableData = (data, columns = 1) => {
  if (columns <= 1) return data;

  const result = [];
  const rowsPerChunk = Math.ceil(data.length / columns);

  // 计算每行应该有多少列（包括分割列）
  const colsPerRow = data[0] ? data[0].length * columns + (columns - 1) : 0;

  for (let chunkIndex = 0; chunkIndex < rowsPerChunk; chunkIndex++) {
    const row = [];

    for (let colIndex = 0; colIndex < columns; colIndex++) {
      const dataIndex = chunkIndex * columns + colIndex;

      // 添加分割列（除了第一列）
      if (colIndex > 0) {
        row.push(true); // gap 列
      }

      // 添加数据列
      if (dataIndex < data.length) {
        // 直接使用原始数组数据
        row.push(...data[dataIndex]);
      } else {
        // 最后一行的长度不够，补充空数据
        const emptyCols = data[0] ? Array(data[0].length).fill("") : [];
        row.push(...emptyCols);
      }
    }

    // 确保每行长度一致
    while (row.length < colsPerRow) {
      row.push("");
    }

    result.push(row);
  }

  return result;
};

/** 表头在左侧的数据处理方法 */
const headerLeftTableData = (header, data) => {
  const result = header.map((title, i) => [
    title,
    ...data.map((row) => row[i]),
  ]);
  return result;
};

/** 分割后的数据 */
const tableDataResult = ref([]);
tableDataResult.value = isHeaderTop.value
  ? headerTopTableData(props.tableData, props.splitNum)
  : headerLeftTableData(props.headerData, props.tableData);
</script>

<style lang="scss" scoped>
$primary-bg: #e4eaf7;
$border-color: #e8e8e8;
$stripe-even-bg: #f8fbff;
$stripe-odd-bg: #ffffff;

$border-radius: 6px;
$border-width: 1px;

// 斑马纹混合宏
@mixin stripe-normal {
  .t-row:nth-child(odd) .t-td:not(.gap-cell) {
    background: $stripe-odd-bg;
  }
  
  .t-row:nth-child(even) .t-td:not(.gap-cell) {
    background: $stripe-even-bg;
  }
}

@mixin stripe-reverse {
  .t-row:nth-child(odd) .t-td:not(.gap-cell) {
    background: $stripe-even-bg;
  }
  
  .t-row:nth-child(even) .t-td:not(.gap-cell) {
    background: $stripe-odd-bg;
  }
}

.super-table-wrapper {
  width: 100%;

  .t-body {
    width: 100%;

    .t-row {
      width: 100%;
      display: grid;
    }
  }

  .t-th:not(.gap-cell),
  .t-td:not(.gap-cell) {
    width: 100%;
    flex: 1;
    min-height: 60px;
    padding: 15px 10px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .t-td {
    display: flex;
    flex-direction: column;
    text-align: center;
    justify-content: center;
  }

  .t-th:not(.gap-cell) {
    background: $primary-bg;
  }

  // 表头在顶部
  &.table-header-top {
    border-radius: $border-radius;
    border-left: $border-width solid $border-color;
    border-right: $border-width solid $border-color;

    // 斑马纹样式
    &.stripe-normal {
      @include stripe-normal;
    }
    
    &.stripe-reverse {
      @include stripe-reverse;
    }

    // 所有 .gap-cell 的前一个单元格
    .t-td:has(+ .gap-cell),
    .t-th:has(+ .gap-cell) {
      border-right: $border-width solid $border-color;

      // 如果是最后一行的前一个单元格
      .t-body .t-row:last-child & {
        border-bottom-right-radius: $border-radius;
        border: 1px solid red;
      }
    }

    // 所有 .gap-cell 的后一个单元格
    .gap-cell + .t-td,
    .gap-cell + .t-th {
      border-left: $border-width solid $border-color;

      // 如果是最后一行的后一个单元格
      .t-body .t-row:last-child & {
        border-bottom-left-radius: $border-radius;
      }
    }

    .t-header {
      width: 100%;
      display: flex;
      font-weight: 500;
      display: grid;

      .t-th {
        &:has(+ .gap-cell) {
          border-top-right-radius: $border-radius;
        }

        &:not(.gap-cell) {
          border-top: $border-width solid $border-color;
        }

        &.gap-cell + .t-th {
          border-top-left-radius: $border-radius;
        }
      }
    }

    .t-body {
      .t-row {
        // grid-template-columns: 1fr 1fr 1fr;
        box-sizing: border-box;

        &:last-child > .t-td:has(+ .gap-cell) {
          border-bottom-right-radius: $border-radius;
        }

        &:last-child > .t-td:not(.gap-cell) {
          border-bottom: $border-width solid $border-color;

          // 选中 .gap-cell 后一个单元格里面的最后一个元素
          &.gap-cell + .t-td > :last-child,
          &.gap-cell + .t-td:not(:has(.t-td)) {
            border-bottom-left-radius: $border-radius;
          }
        }
      }
    }
  }

  // 表头在左测的样式
  &.table-header-left {
    .t-body {
      background-color: $stripe-even-bg;

      .t-row {
        & > .t-td {
          flex-direction: row;
        }
      }

      .t-row > .t-td:first-child {
        background-color: $primary-bg;
        font-weight: 500;
      }

      // .t-row:nth-child(2n) .t-td:nth-child(n + 2) {
      //   background: #e8f2fd;
      // }
    }
  }
}
</style>
